package com.chinda.common.exception;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.chinda.common.enums.MessageEnum;
import com.chinda.common.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 异常
 * @author Wang Chinda
 * @date 2020/8/8
 * @see
 * @since 1.0
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @Value("${spring.servlet.multipart.max-file-size:10MB}")
    private String maxFileSize;

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R exceptionHandler(Exception e) {
        log.error(MessageEnum.SYS_CHECK_0001.getMsg(), e);
        return R.error(MessageEnum.SYS_CHECK_0001.getMsg());
    }

    @ExceptionHandler(RRException.class)
    public R rrExceptionHandler(RRException e) {
        return R.error(e.getMessage());
    }

    /**
     * @Valid全局异常处理
     * @param e
     * @return
     */
    @ExceptionHandler({MethodArgumentNotValidException.class})
    public R validExceptionHandler(MethodArgumentNotValidException e) {
        log.error(MessageEnum.SYS_CHECK_0002.getMsg(), e);
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        List<String> errorMessages = CollUtil.newArrayList();
        Iterator<FieldError> var5 = fieldErrors.iterator();

        while(var5.hasNext()) {
            FieldError error = var5.next();
            errorMessages.add(StrUtil.format("[{} ==> {}]",error.getField(), error.getDefaultMessage()));
        }
        return R.error(errorMessages.stream().collect(Collectors.joining(StrUtil.COMMA)));
    }

    @ExceptionHandler(DuplicateKeyException.class)
    public R duplicateKeyExceptionHandler(DuplicateKeyException e){
        log.error(MessageEnum.SYS_CHECK_0003.getMsg("已存在"), e);
        return R.error(MessageEnum.SYS_CHECK_0003.getMsg("已存在"));
    }

    @ExceptionHandler(EmptyResultDataAccessException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R emptyResultDataAccessExceptionHandler(EmptyResultDataAccessException e) {
        log.error(MessageEnum.SYS_CHECK_0003.getMsg("不存在"), e);
        return R.error(MessageEnum.SYS_CHECK_0003.getMsg("不存在"));
    }

    @ExceptionHandler(BadSqlGrammarException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R emptyResultDataAccessExceptionHandler(BadSqlGrammarException e) {
        log.error(MessageEnum.SYS_CHECK_0004.getMsg(), e);
        return R.error(MessageEnum.SYS_CHECK_0004.getMsg());
    }

    @ExceptionHandler(OptimisticLockingFailureException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R optimisticLockingFailureException(OptimisticLockingFailureException e) {
        log.error(MessageEnum.SYS_CHECK_0005.getMsg(), e);
        return R.error(MessageEnum.SYS_CHECK_0005.getMsg());
    }

    @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R optimisticLockingFailureException(HttpMessageNotReadableException e) {
        log.error(MessageEnum.SYS_CHECK_0006.getMsg(), e);
        return R.error(MessageEnum.SYS_CHECK_0006.getMsg());
    }

    @ExceptionHandler(NoHandlerFoundException.class)
    public R handlerNoFoundException(Exception e) {
        log.error(MessageEnum.SYS_CHECK_0015.getMsg(), e);
        return R.error(MessageEnum.SYS_CHECK_0015.getMsg());
    }

    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public R handlerHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e){
        String param1 = e.getMethod();
        String param2 = Arrays.stream(e.getSupportedMethods()).collect(Collectors.joining(StrUtil.COMMA));
        log.error(MessageEnum.SYS_CHECK_0016.getMsg(param1, param2), e);
        return R.error(MessageEnum.SYS_CHECK_0016.getMsg(param1, param2));
    }

    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public R handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e) {
        log.error(MessageEnum.SYS_CHECK_0017.getMsg(maxFileSize), e);
        return R.error(MessageEnum.SYS_CHECK_0017.getMsg(maxFileSize));
    }

    @ExceptionHandler(DataIntegrityViolationException.class)
    public R handleDataIntegrityViolationException(DataIntegrityViolationException e) {
        log.error(MessageEnum.SYS_CHECK_0018.getMsg(), e);
        return R.error(MessageEnum.SYS_CHECK_0018.getMsg());
    }

    @ExceptionHandler(AccessDeniedException.class)
    public R handleAccessDeniedException(AccessDeniedException e) {
        log.error(MessageEnum.SYS_CHECK_0019.getMsg(MessageEnum.SYS_SECURITY_0007.getMsg()), e);
        return R.error(MessageEnum.SYS_CHECK_0019.getMsg(MessageEnum.SYS_SECURITY_0007.getMsg()));
    }
}
